package redis

import (
	"context"
	"errors"
	"sync"

	"gitee.com/zacyuan/yuan/pkg/config"
	"github.com/redis/go-redis/v9"
)

const (
	configNode = "redis"
)

var (
	rds  sync.Map
	once sync.Once
)

func GetDefault() *Client {
	return GetByNode("default")
}

func GetByNode(node string, ctx ...context.Context) *Client {
	client, ok := rds.Load(node)
	if !ok {
		return nil
	}

	return client.(*Client)
}

func Open(cfg *Config) (*Client, error) {
	if cfg.Name == "" {
		return nil, errors.New("name is empty.")
	}

	client := redis.NewClient(&redis.Options{
		Addr:     cfg.Addr,
		Password: cfg.Password,
	})

	_, err := client.Ping(context.Background()).Result()
	if err != nil {
		return nil, err
	}

	if cfg.WriteLog {
		client.AddHook(NewLogHook())
	}

	for _, hook := range cfg.Hooks {
		client.AddHook(hook)
	}

	rds.Store(cfg.Name, client)
	return client, nil
}

func Start() error {
	var err error
	once.Do(func() {
		list := make(map[string]any)
		err = config.UnmarshalKey(configNode, &list)
		if err != nil {
			return
		}

		for one := range list {
			key := configNode + "." + one
			cfg := DefaultConfig()
			err = config.UnmarshalKey(key, cfg)
			if err != nil {
				return
			}

			if cfg.Startup {
				if cfg.Name == "" {
					cfg.Name = one
				}
				_, err = Open(cfg)
				if err != nil {
					return
				}
			}
		}

	})
	return err
}
